from typing import Type
from bcat.gtp.serde.dev2.imap_access import IMapAccess

from bcat.gtp.serde.error import NeedAlphaError, PairEndError

from bcat.gtp.serde.dev2.ideserializer import IDeserializer
from bcat.gtp.serde.dev2.ireader import IReader
from bcat.gtp.serde.dev2.valid.ivalidate import IValidate
from bcat.gtp.serde.dev2.impl.special_char import SpecialChar

class MapAccess(IMapAccess):
    def __init__(self, deserializer):
        super().__init__(deserializer)
        self.__first = True

    def has_next_entry(self):
        reader: IReader = self.deserializer().reader()
        if self.__first:
            byte = reader.peek_or_raise()
            if SpecialChar.is_alpha(byte): #must be the key
                self.__first = False
                return True
            else:
                raise NeedAlphaError(reader.position())
        else: # not first key
            byte = reader.peek_or_raise()
            if SpecialChar.is_pair_separator(byte):
                reader.eat()
                byte = reader.peek_or_raise() 
                if SpecialChar.is_alpha(byte): #must be key
                    return True
                else:
                    raise NeedAlphaError(reader.position())
            elif SpecialChar.is_object_end(byte):
                return False
            else:
                msg = "unknow byte:({}:{}), expect:(}} or ,) for test has_next_entry".format(chr(byte) if byte <= 0x8f else byte, byte)
                raise PairEndError(reader.position(), msg)
            
    #True or False or Exception  (True|False, True|False)
    def next_entry(self, key_type=None, value_type=None):
        k = self._next_key(key_type)
        if k :
            return (k , self._next_value(value_type))
        else:
            return (False, False)

    #-> True or False or Exception
    def _next_key(self, key_type: Type[IValidate]):
        return key_type().validate(self.deserializer())
    #-> True or False or Exception
    def _next_value(self, value_type: Type[IValidate]):
        self.deserializer().deser_kv_separator()
        return value_type().validate(self.deserializer())
